# coding: utf-8
from datetime import datetime
from pathlib import Path

from httpx import stream

from common import signalBus, TaskMessage, TaskStatus, Task, TaskDao, COVER_DIR
from .runner_base import DownRunnableBase
from .tools import speed_to_str, get_video_cover, get_file_size
from ..db_thread import send_sql_request


class StreamRunner(DownRunnableBase):
    def __init__(self, task: Task, *, method: str = "GET"):
        super().__init__(task)
        self.method = method
        self.temp_file = Path(self.save_file).with_suffix('.temp')

        self.isFinished = False
        self.speed = 0
        self.isStop = False

    def run(self):
        task_msg = TaskMessage(
            id=self.tid,
        )
        if self.isStop:
            task_msg.status = TaskStatus.CANCEL
            task_msg.message = "任务已取消"
            signalBus.taskMsgSig.emit(task_msg)
            return
        task_msg.status = TaskStatus.DOING
        task_msg.message = "开始解析数据"
        signalBus.taskMsgSig.emit(task_msg)

        if self.save_file.exists():
            task_msg.status = TaskStatus.DONE
            task_msg.message = "文件已存在，跳过下载"
            signalBus.taskMsgSig.emit(task_msg)
            return

        self.temp_file.touch(exist_ok=True)
        size = get_file_size(self.temp_file)
        download_size = 0

        headers = self.headers or {}

        headers.update({'Range': f'bytes={size}-'})
        start_time = datetime.now()
        try:
            with stream(
                    self.method,
                    self.url,
                    headers=headers,
                    timeout=10,
                    follow_redirects=True,
                    verify=False,
            ) as response:
                response.raise_for_status()
                length = int(response.headers.get('Content-Length', 0))

                task_msg.message = f"文件大小：{speed_to_str(length)}"
                task_msg.downloaded_msg = f'0 MB / {speed_to_str(length)}'
                signalBus.taskMsgSig.emit(task_msg)

                with self.temp_file.open('a+b') as f:
                    for chunk in response.iter_bytes():
                        f.write(chunk)
                        download_size += len(chunk)
                        current_time = datetime.now()
                        elapsed_time = (current_time - start_time).total_seconds()
                        speed = download_size / elapsed_time if elapsed_time > 0 else 0

                        mg = f'{speed_to_str(download_size + size)} / {speed_to_str(length)}'
                        pg = round((download_size + size) / length, 4) * 100
                        task_msg.message = f'正在下载，百分比：{int(pg)} %，进度：{mg}'
                        task_msg.progress = pg
                        task_msg.downloaded_msg = mg
                        task_msg.net_speed = speed_to_str(speed) + '/S'
                        signalBus.taskMsgSig.emit(task_msg)

                        if self.isStop:
                            task_msg.status = TaskStatus.PAUSE
                            task_msg.message = "任务已暂停"
                            signalBus.taskMsgSig.emit(task_msg)
                            break

                if get_file_size(self.temp_file) >= length:
                    self.isFinished = True
                    task_msg.message = "下载完成"
                    signalBus.taskMsgSig.emit(task_msg)
        except Exception as e:
            task_msg.status = TaskStatus.ERROR
            task_msg.message = f"下载失败：{e}"
            signalBus.taskMsgSig.emit(task_msg)

        if self.isFinished:
            self.temp_file.rename(self.save_file)
            if self.save_file.suffix.lower() not in ['.mp4', '.mkv', '.flv', '.ts', '.avi', '.rmvb', '.wmv', '.mov',
                                                     '.rm']:
                return
            task_msg.message = "准备生成封面"
            signalBus.taskMsgSig.emit(task_msg)
            cover = get_video_cover(self.save_file)
            cover_path = (COVER_DIR / f'{self.tid}.png').as_posix()
            cover.save(cover_path)
            send_sql_request(TaskDao.update_by_id, Task(id=self.tid, cover=cover_path))
            task_msg.cover = cover_path
            task_msg.message = "封面生成完成, 文件已保存下载完毕"
            task_msg.status = TaskStatus.DONE
            signalBus.taskMsgSig.emit(task_msg)

    def stop(self):
        self.isStop = True

    def start(self):
        runner = StreamRunner(self.task)
        signalBus.taskReAddSig.emit(runner)
        return runner
